package cate.common.util.random;

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.apache.commons.collections4.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 带权重的随机列表
 */
public class RWList<E extends RWItem> {

    public List<E> list;

    private List<WeightItem> weightItems;

    public RWList(){

    }

    public RWList(Collection<E> c) {
        addAll(c);
    }

    public void add(E item) {
        if (list == null) {
            list = new ArrayList<>();
        }
        list.add(item);
    }

    public void addAll(Collection<E> c) {
        if (list == null) {
            list = new ArrayList<>();
        }
        list.addAll(c);
    }

    public RWList<E> addAndSetup(Collection<E> c) {
        addAll(c);
        return setup();
    }

    /**
     * 设置权重
     */
    public RWList<E> setup() {
        return setup(null);
    }

    /**
     * 设置权重
     */
    public RWList<E> setup(List<E> list) {
        if (this.list == null) {
            this.list = list;
        }
        if (this.list == null) {
            return this;
        }
        double weightTotal = 0;
        for (E item : this.list) {
            weightTotal += item.getWeight();
        }
        weightItems = new ArrayList<>();
        double weight = 0;
        for (int idx=0; idx<this.list.size(); ++idx) {
            weight += this.list.get(idx).getWeight();
            weightItems.add(new WeightItem(idx, weight / weightTotal));
        }
        return this;
    }

    /**
     * 获取权重和
     */
    @JsonIgnore
    public double getWeightTotal() {
        double weightTotal = 0;
        for (E item : this.list) {
            weightTotal += item.getWeight();
        }
        return weightTotal;
    }

    /**
     * 随机获得
     */
    public E get() {
        if (list == null || list.isEmpty() || weightItems == null || weightItems.size() != list.size()) {
            return null;
        }
        double pos = Math.random();
        for (WeightItem item : weightItems) {
            if (pos <= item.getWeightPos()) {
                return list.get(item.getIndex());
            }
        }
        return null;
    }

    @JsonIgnore
    public boolean isEmpty() {
        return CollectionUtils.isEmpty(list);
    }

    public boolean isNotEmpty() {
        return !isEmpty();
    }

    public void clear(){
        if(CollectionUtils.isNotEmpty(list)){
            list.clear();
        }
    }

    private static class WeightItem{
        private int index;
        private double weightPos;

        public WeightItem(int index, double weightPos){
            this.index = index;
            this.weightPos = weightPos;
        }

        public double getWeightPos(){
            return this.weightPos;
        }
        public int getIndex(){
            return this.index;
        }
    }
}
